package com.amex.uam.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.amex.uam.dao.AmexBusDao;
import com.amex.uam.dao.DeptDao;
import com.amex.uam.dao.MstrDao;
import com.amex.uam.dao.UserDao;
import com.amex.uam.model.AMEX_BUSINESS;
import com.amex.uam.model.AMEX_UNIT;
import com.amex.uam.model.MS_USER_ADMIN;
import com.amex.uam.model.MS_USER_CTRY_ACSS;
import com.amex.uam.model.MS_USER_PROJ;
import com.amex.uam.model.MS_USER_RGN_ACSS;
import com.amex.uam.model.Message;
import com.amex.uam.model.USER_DEPT;
import com.amex.uam.service.UserService;
import com.amex.uam.util.Utils;
import com.microstrategy.web.objects.WebIServerSession;
import com.microstrategy.web.objects.admin.users.WebUser;

@Service("userService")
public class UserServiceImpl implements UserService {
	private UserDao userDao;
	private MstrDao mstrDao;
	private DeptDao deptDao;
	private AmexBusDao amexBusDao;

	@Resource //byName default injection
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	@Resource
	public void setMstrDao(MstrDao mstrDao) {
		this.mstrDao = mstrDao;
	}
	@Resource
	public void setDeptDao(DeptDao deptDao) {
		this.deptDao = deptDao;
	}
	@Resource
	public void setAmexBusDao(AmexBusDao amexBusDao) {
		this.amexBusDao = amexBusDao;
	}
	
	public Message loadUserByAmexWebId(String amexWebId) {
		Message msg = new Message();
		if (amexWebId == null || amexWebId.length() == 0) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("amexWebId is invalid.");
		} else {
			msg.setStatus(Message.OK);
			msg.setData(userDao.loadUserByAmexWebId(amexWebId));
		}
		return msg;
	}
	
	@Override
	public Message addUser(MS_USER_ADMIN user) {
		Message msg = new Message();
		if (user == null || Utils.isEmpty(user.getWORKFORCE_MBR_ID()) || Utils.isEmpty(user.getUSER_ID())) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("user is invalid.");
		} else {
			boolean success = userDao.addUser(user);
			return success ? msg.setStatus(Message.OK) : msg.setStatus(Message.ERROR); 
		}
		return msg;
	}
	
	@Override
	public Message searchUser(String searchParam, String searchDBFldString, WebIServerSession session) {
		Message msg = new Message();
		try {
		if (searchParam == null) {
			msg.setStatus(Message.ERROR_PARAM);
		} else {
			msg.setStatus(Message.OK);
			List<Map<String, String>> list = userDao.searchUser(searchParam, searchDBFldString);
			for (Iterator it = list.iterator(); it.hasNext();) {
				Map<String, String> map = (Map<String, String>) it.next();
				WebUser user = mstrDao.searchUser(map.get("USER_ID"), session);
				if (user == null) {
					map.put("STATUS", "undefined");
				} else {
					user.populate();
					map.put("STATUS", String.valueOf(user.isEnabled()));
				}
			}
			
			msg.setData(list);
		}
		}catch(Throwable t) {
			t.printStackTrace();
		}
		return msg;
	}

	@Override
	public Message loadUserProfile(String userId) {
		Message msg = new Message();
		
		if (userId == null) {
			msg.setStatus(Message.ERROR_PARAM);
		} else {
			msg.setStatus(Message.OK);
			msg.setData(userDao.loadUserProfile(userId));
		}
		return msg;
	}
	
	@Override
	public Message loadUserSecurityGroup(String amexWebId) {
		Message msg = new Message();
		if (amexWebId == null) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("amexWebId is invalid.");
		} else {
			msg.setStatus(Message.OK);
			msg.setData(userDao.loadUserSecurityGroup(amexWebId));
		}
		return msg;
	}

	@Override
	public Message loadGEOCTRYByAmexWebId(String amexWebId) {
		Message msg = new Message();
		if (amexWebId == null) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("amexWebId is invalid.");
		} else {
			msg.setStatus(Message.OK);
			msg.setData(userDao.loadGEOCTRYByAmexWebId(amexWebId));
		}
		return msg;
	}

	@Override
	public Message loadGEORGNByAmexWebId(String amexWebId) {
		Message msg = new Message();
		if (amexWebId == null) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("amexWebId is invalid.");
		} else {
			msg.setStatus(Message.OK);
			msg.setData(userDao.loadGEORGNByAmexWebId(amexWebId));
		}
		return msg;
	}

	@Override
	public int updateVUPUSRGenInfo(MS_USER_ADMIN mua) {
		Message msg = new Message();
		int result = 0;
		if (mua == null) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("mua is invalid.");
			//Logger.
		} else {
			msg.setStatus(Message.OK);
			result = userDao.updateVUPUSRGenInfo(mua);
		}
		return result;
	}

	@Override
	public boolean updateVUPUSRDept(USER_DEPT ud) {
		return deptDao.updateDepartment(ud);
	}

	@Override
	public int updateVUPUSRAmexBuss(AMEX_BUSINESS ab) {
		return userDao.updateVUPUSRAmexBuss(ab);
	}

	@Override
	public int updateVUPUSRAmexUnit(AMEX_UNIT au) {
		return userDao.updateVUPUSRAmexUnit(au);
	}

	@Override
	public Message addMstrProd(String mstrProd, String amexWebId) {
		if (amexWebId == null || amexWebId.equals("")) {
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid");
		}
		if (mstrProd != null) {
			List<MS_USER_PROJ> list = new ArrayList<MS_USER_PROJ>();
			String[] items = mstrProd.split(",");
			for (int i = 0; i < items.length; i++) {
				int id = Utils.parseInt(items[i], -1);
				if (id != -1) {
					MS_USER_PROJ u = new MS_USER_PROJ();
					u.setWORKFORCE_MBR_ID(amexWebId);
					u.setMS_PROJ_ID(id);
					u.setCREAT_TS(new Timestamp(System.currentTimeMillis()));
					list.add(u);
				}
			}
			userDao.addMstrProd(list);
		}
		return new Message(Message.OK);
	}
	
	@Override
	public Message updateVUPMSTRProd(String mstrProd, String amexWebId) {
		if (amexWebId == null || amexWebId.equals("")) {
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid");
		}
		if (mstrProd != null) {
			List<MS_USER_PROJ> list = new ArrayList<MS_USER_PROJ>();
			String[] items = mstrProd.split(",");
			for (int i = 0; i < items.length; i++) {
				int id = Utils.parseInt(items[i], -1);
				if (id != -1) {
					MS_USER_PROJ u = new MS_USER_PROJ();
					u.setWORKFORCE_MBR_ID(amexWebId);
					u.setMS_PROJ_ID(id);
					u.setCREAT_TS(new Timestamp(System.currentTimeMillis()));
					list.add(u);
				}
			}
			userDao.updateVUPMSTRProd(list);
		}
		return new Message(Message.OK);
	}
	
	@Override
	public Message addUserGroup(String amexWebId, String groupName) {
		if (amexWebId == null || amexWebId.length() == 0){ 
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid.");
		}
		
		if (groupName == null || groupName.length() == 0) { 
			return new Message(Message.OK); 
		}
		
		
		boolean success = this.userDao.attachUserToGroup(amexWebId, groupName);
		
		return success ? new Message(Message.OK) : new Message(Message.ERROR);
	}
	
	@Override
	public Message updateUserGroup(String amexWebId, String originalVal, String modifiedVal) {
		if (amexWebId == null || amexWebId.length() == 0) 
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid.");
		
		if (modifiedVal == null) {
			if (originalVal != null) {
				this.userDao.removeUserFromGroup(amexWebId, originalVal);
			} 
			return new Message(Message.OK); 
		} else if(! modifiedVal.equals(originalVal)) {
			if (originalVal != null) {
				this.userDao.removeUserFromGroup(amexWebId, originalVal);
			}
		}
		
		this.userDao.attachUserToGroup(amexWebId, modifiedVal);
		
		return new Message(Message.OK);
	}

	@Override
	public Message addMarcFuncGroup(String amexWebId, String marcFuncVal) {
		if (amexWebId == null || amexWebId.length() == 0) 
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid.");
		
		Set<String> addList = new HashSet<String>();
		if (marcFuncVal != null) {
			String[] groups = marcFuncVal.split(",");
			for (String groupName : groups) {
				groupName = groupName.trim();
				if (groupName.length() > 0) {
					addList.add(groupName);
				}
			}
		}
		for (Iterator<String> it = addList.iterator(); it.hasNext();) {
			String groupName =  it.next();
			this.userDao.attachUserToGroup(amexWebId, groupName);
		}
		
		return new Message(Message.OK);
	}
	@Override
	public Message updateMarcFuncGroup(String userId, String amexWebId, String marcFuncOri, String marcFuncVal, WebIServerSession session) {
		
		if (userId == null || userId.length() == 0) 
			return new Message(Message.ERROR_PARAM, "userId is invalid.");
		if (amexWebId == null || amexWebId.length() == 0) 
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid.");
		
		Set<String> mixedSet = new HashSet<String>();
		Set<String> addList = new HashSet<String>();
		HashSet<String> removeList = new HashSet<String>();
		
		//System.out.println("MARC Functional Group - modified: " + marcFuncVal);
		if (marcFuncVal != null) {
			String[] groups = marcFuncVal.split(",");
			for (String groupName : groups) {
				if (groupName.trim().length() > 0) {
					addList.add(groupName);
				}
			}
		}
		//System.out.println("MARC Functional Group - original: " + marcFuncOri);
		if (marcFuncOri != null) {
			String[] groups = marcFuncOri.split(",");
			for (String groupName : groups) {
				if (groupName.trim().length() > 0) {
					if (mixedSet.contains(groupName))
						continue;
					if (addList.contains(groupName)) {
						addList.remove(groupName);
						mixedSet.add(groupName);
					} else {
						removeList.add(groupName);
					}
				}
			}
		}
		/*System.out.println("** add.list:");
		printSet(addList, "-->");
		System.out.println("** remove.list:");
		printSet(removeList, "-->");
		System.out.println("** mixed.list:");
		printSet(mixedSet, "-->");*/
		
		for (Iterator<String> it = addList.iterator(); it.hasNext();) {
			String groupName =  it.next();
			this.userDao.attachUserToGroup(amexWebId, groupName);
			this.mstrDao.attachUserToGroup(userId, groupName, session);
		}
		for (Iterator<String> it = mixedSet.iterator(); it.hasNext();) {
			String groupName =  it.next();
			this.userDao.attachUserToGroup(amexWebId, groupName);
			this.mstrDao.attachUserToGroup(userId, groupName, session);
		}
		for (Iterator<String> it = removeList.iterator(); it.hasNext();) {
			String groupName = it.next();
			this.userDao.removeUserFromGroup(amexWebId, groupName);
			this.mstrDao.removeUserFromGroup(userId, groupName, session);
		}
		
		return new Message(Message.OK);
	}
	
	@SuppressWarnings("rawtypes")
	private void printSet(Set<String> set, String prefix) {
		for (Iterator it = set.iterator(); it.hasNext();) {
			String item = (String) it.next();
			if (prefix == null) prefix = "";
			System.out.println(prefix + item);
		}
	}

	@Override
	public Message updateRGN(String lifExcepRegion, String amexWebId) {
		if (amexWebId == null || amexWebId.equals("")) {
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid");
		}
		if (lifExcepRegion != null) {
			List<MS_USER_RGN_ACSS> list = new ArrayList<MS_USER_RGN_ACSS>();
			String[] items = lifExcepRegion.split(",");
			for (int i = 0; i < items.length; i++) {
				MS_USER_RGN_ACSS u = new MS_USER_RGN_ACSS();
				u.setWORKFORCE_MBR_ID(amexWebId);
				u.setRGN_ABBR_NM(items[i]);
				u.setCREAT_TS(new Timestamp(System.currentTimeMillis()));
				list.add(u);
			}
			userDao.updateRGN(list);
		}
		return new Message(Message.OK);
	}

	@Override
	public Message updateCTRY(String lifExcepCountry, String amexWebId) {
		if (amexWebId == null || amexWebId.equals("")) {
			return new Message(Message.ERROR_PARAM, "amexWebId is invalid");
		}
		if (lifExcepCountry != null) {
			List<MS_USER_CTRY_ACSS> list = new ArrayList<MS_USER_CTRY_ACSS>();
			String[] items = lifExcepCountry.split(",");
			for (int i = 0; i < items.length; i++) {
				MS_USER_CTRY_ACSS u = new MS_USER_CTRY_ACSS();
				u.setWORKFORCE_MBR_ID(amexWebId);
				u.setCTRY_NM(items[i]);
				u.setCREAT_TS(new Timestamp(System.currentTimeMillis()));
				list.add(u);
			}
			userDao.updateCTRY(list);
		}
		return new Message(Message.OK);
	}
	@Override
	public Message editUserGeneralInfo(MS_USER_ADMIN user) {
		Message msg = new Message();
		if (user == null || Utils.isEmpty(user.getWORKFORCE_MBR_ID()) || Utils.isEmpty(user.getUSER_ID())) {
			msg.setStatus(Message.ERROR_PARAM);
			msg.setData("user is invalid.");
		} else {
			boolean success = userDao.editUserGeneralInfo(user);
			return success ? msg.setStatus(Message.OK) : msg.setStatus(Message.ERROR); 
		}
		return msg;
	}
	
	@Override
	public Message removeUser(String userIds) {
		if (userIds == null || userIds.trim().length() == 0) {
			return new Message(Message.ERROR_PARAM, "userIds is invalid.");
		}
		
		String[] idList = userIds.split(",");
		for (String userId : idList) {
			if (userId.trim().length() == 0) {
				continue;
			}
			userDao.removeUser(userId);
		}
		
		return new Message(Message.OK);
	}
}

